package com.liu.redis.controller;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author LIU
 * @version 1.0
 * @date 2024/4/26 10:39
 * @description TODO
 * 在Redisson中，使用key来作为是否上锁的标志，当通过getLock(String key)方法获得相应的锁之后，这个key即作为一个锁存储到Redis集群中，
 * 在接下来如果有其他的线程尝试获取名为key的锁时，便会向集群中进行查询，如果能够查到这个锁并发现相应的value的值不为0，
 * 则表示已经有其他线程申请了这个锁同时还没有释放，则当前线程进入阻塞，否则由当前线程获取这个锁并将value值加一，
 *
 * 如果是可重入锁的话，则当前线程每获得一个自身线程的锁，就将value的值加一，而每释放一个锁则将value值减一，
 * 直到减至0，完全释放这个锁。因为底层是基于分布式的Redis集群，所以Redisson实现了分布式的锁机制。
 */
@RestController
public class RedissonLockController {

    @Autowired
    public RedissonClient redisson;

    @GetMapping("hello")
    public String hello() {
        // 获取锁，只能要是名字一样，就是同一把锁
        RLock lock = redisson.getLock("my-lock");

        // 加锁，阻塞式等待，默认30s
        lock.lock();
        // 1.锁自动续期，如果业务超长，运行期间自动给锁续期30s
        // 2.业务完成就不会自动续期，即使不手动解锁，锁默认30s后也自动删除


        try {
            System.out.println("加锁成功，执行业务。。。"+ Thread.currentThread().getId());

            Thread.sleep(30000);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("释放锁。。。" + Thread.currentThread().getId());
            // 解锁，如果解锁代码没有执行，redisson也不会死锁
            lock.unlock();
        }

        return "hello";
    }
}
